//
//  ina220.c
//  NMEA
//
//  Created by Hans Johnson on 2014-03-31.
//
//

#include "avr_compiler.h"
#include <stdio.h>
#include <avr/eeprom.h>
#include "status_codes.h"
#include "ina220.h"
#include "twim.h"

// INA220 Calibration Data
#ifndef __APPLE__
uint16_t EEMEM ina220cal[2] = {0,0};
#else
uint16_t ina220cal[2] = {0,0};
#endif

// Function to initialize the ina220

status_code_t ina220_init(uint8_t addr)
{
    // Package to send data out over the twi
    twi_package_t   data;
    
    // Status variable
    status_code_t status;
    
    // Data to send out
    uint16_t confreg;
    
    // calibration
    uint16_t calibration;
    
    switch (addr) {
        case INA220a_ADDR:
            calibration = eeprom_read_word(&ina220cal[0]);
            break;
        case INA220b_ADDR:
            calibration = eeprom_read_word(&ina220cal[1]);
            break;
        default:
            return ERR_BAD_ADDRESS;
            break;
    }
    
    confreg = (INA220_CNF_PGA_160mv | (INA220_CNF_ADC_64AV << INA220_CNF_BADC_bp) |
               (INA220_CNF_ADC_64AV << INA220_CNF_SADC_bp) | INA220_CNF_MODE_SBVC);
    
    // Configuration
    data.chip = addr;
    data.addr[0] = INA220_CNF;
    data.addr_length = 1;
    data.buffer = &confreg;
    data.length = 2;
    data.no_wait = false;
    
    // send the config reg out
    status = twi_master_write(&TWID, &data);
    if (status != STATUS_OK) {
        return status;
    }
    
    // send the calibration data
    data.addr[0] = INA220_CAL;
    data.buffer = &calibration;
    data.length = 2;
    
    return twi_master_write(&TWID, &data);
    
}

// Function to shut down the INA220
status_code_t ina220_shutdown(uint8_t addr)
{
    // package to read/write data from the TWI
    twi_package_t data;
    
    // configuration data
    uint16_t confreg;
    
    // status code for returning things
    status_code_t status;
    
    // check to make sure we have an INA220
    if ((addr == INA220a_ADDR)|(addr == INA220b_ADDR))
    {
        // set the chip address
        data.chip = addr;
        // Set the internal register
        data.addr[0] = INA220_CNF;
        data.addr_length = 1;
        // setup the buffer/length
        data.buffer = &confreg;
        data.length = 2;
        data.no_wait = false;
        
        // read the config register from the bus
        status = twi_master_read(&TWID, &data);
        if (status != STATUS_OK)
        {
            return status;
        }
        
        // set the mode to 0, which powers it down
        confreg &= ~(INA220_CNF_MODE_gm);
        
        // write the configuration back out to the device
        return twi_master_read(&TWID, &data);
    }
    // we've given a bad address
    return ERR_BAD_ADDRESS;
}

// Function to shut down the INA220
status_code_t ina220_run(uint8_t addr)
{
    // package to read/write data from the TWI
    twi_package_t data;
    
    // configuration data
    uint16_t confreg;
    
    // status code for returning things
    status_code_t status;
    
    // check to make sure we have an INA220
    if ((addr == INA220a_ADDR)|(addr == INA220b_ADDR))
    {
        // set the chip address
        data.chip = addr;
        // Set the internal register
        data.addr[0] = INA220_CNF;
        data.addr_length = 1;
        // setup the buffer/length
        data.buffer = &confreg;
        data.length = 2;
        data.no_wait = false;
        
        // read the config register from the bus
        status = twi_master_read(&TWID, &data);
        if (status != STATUS_OK)
        {
            return status;
        }
        
        // set the mode continues operation
        confreg |= INA220_CNF_MODE_SBVC;
        
        // write the configuration back out to the device
        return twi_master_read(&TWID, &data);
    }
    // we've given a bad address
    return ERR_BAD_ADDRESS;
}

// Read Value from ina220
status_code_t ina220_read(uint8_t addr, uint8_t reg, int16_t *value)
{
    // package to read/write data from the TWI
    twi_package_t data;
    
    // check to make sure we have an INA220
    if ((addr == INA220a_ADDR)|(addr == INA220b_ADDR))
    {
        // Setup for the transfer
        data.chip = addr;
        // put in which register we'll be reading
        data.addr[0] = reg;
        data.addr_length = 1;
        // value that will be read back
        data.buffer = value;
        // all registers that will be read are two bytes long
        data.length = 2;
        data.no_wait = false;
        
        // read the register in
        return twi_master_read(&TWID, &data);
    }
    return ERR_BAD_ADDRESS;
}

// Function to set the calibration data for the INA
void ina220_calibrate(uint8_t addr, int16_t curent, int16_t millivolts)
{
    
}



